import re
import sys

def read(file_name: str) -> str:
    '''
    读取一个coe文件。

    Parameters
    ----------
    file_name : str
        coe文件路径。

    Returns
    -------
    out : str
        不带0x前缀的十六进制字符串。

    Notes
    -----
    目前仅支持读取以2进制、8进制或16进制存放的coe数据。
    '''

    with open(file_name, "r") as f: # 打开coe
        coe_data = f.read()
        radix_line = re.search('memory_initialization_radix.*?=.*?\d*', coe_data, re.I).group()
        radix: int = int(re.search('\d+', radix_line).group()) # 获取数据进制(以10进制表示)

        match radix:
            case 16:
                origin_data_list = re.findall('\w*', coe_data[coe_data.index("=",coe_data.index(";"))+1:]) # 拿到数据列表
                origin_data: str = ""
                for item in origin_data_list:
                    if len(item) > 0:
                        origin_data = origin_data + item
                return origin_data
            
            case 8:
                origin_data_list = re.findall('[01234567]*', coe_data[coe_data.index("=",coe_data.index(";"))+1:]) # 拿到数据列表
                origin_data: str = "" # 拿到八进制数据
                for item in origin_data_list:
                    if len(item) > 0:
                        origin_data = origin_data + item
                hex_data: str = "" # 转十六进制
                for index in range(0,len(origin_data),4): # 四个八进制字符对应三个十六进制字符
                    t = hex(int(origin_data[index:index+4], 2))[2:]
                    hex_data += "0"*(3-len(t))+t
                return hex_data

            case 2:
                origin_data_list = re.findall('[01]*', coe_data[coe_data.index("=",coe_data.index(";"))+1:]) # 拿到数据列表
                origin_data: str = "" # 拿到二进制数据
                for item in origin_data_list:
                    if len(item) > 0:
                        origin_data = origin_data + item
                hex_data: str = "" # 转十六进制
                for index in range(0,len(origin_data),4): # 四个二进制字符对应一个十六进制字符
                    hex_data += hex(int(origin_data[index:index+4], 2))[2:]
                return hex_data

            case _:
                print("##### 不支持的数据进制 #####")
                sys.exit(0)

def write(file_name: str, data: str, radix: str, width: int) -> None:
    '''
    生成一个coe文件。

    Parameters
    ----------
    file_name : str
        输出文件路径
    data : str
        不带0x前缀的十六进制字符串
    radix : str
        目标进制, 目前支持: 'BIN', 'HEX'
    width : int
        目标宽度
    '''

    match radix:
        case "HEX":
            fake_width = width//4 # 16进制输出，宽度必须为4的整数倍
            patch_length = fake_width-len(data)%fake_width
            if patch_length != fake_width: # 需要末尾补零
                data=data+"0"*patch_length
            with open(file_name, "w") as f: # 创建coe文件
                f.write("memory_initialization_radix=16;\n")
                f.write("memory_initialization_vector=")
                for index in range(0,len(data),fake_width):
                    f.write("\n"+data[index:index+fake_width])
                f.write(";")

        case "BIN":
            b_data = "" # 转二进制
            for index in range(0,len(data),2):
                byte_data = bin(int(data[index:index+2], 16))[2:]
                b_data += "0"*(8-len(byte_data))+byte_data
            patch_length = width-len(b_data)%width
            if patch_length != width: # 需要末尾补零
                b_data=b_data+"0"*patch_length
            with open(file_name, "w") as f: # 创建coe文件
                f.write("memory_initialization_radix=2;\n")
                f.write("memory_initialization_vector=")
                for index in range(0,len(b_data),width):
                    f.write("\n"+b_data[index:index+width])
                f.write(";")

        case _:
            print("##### 不支持的数据进制 #####")
            sys.exit(0)